import PersonList
import numpy as np

MyCount = 0
AllProbably = [] #用来记录所有可能的上班表
# 排班算法主要程序
def ScheduledAlgo():
    # 拿到所有人的计划
    all_person = PersonList.RandomFun(7)
    # 该表装载上班的映射矩阵
    scheduled_rule = []
    # 该表装载上班的映射矩阵
    scheduled_list = np.zeros((6,7),dtype=int)

    # print("all_person",all_person)
    # print("scheduled_list",scheduled_list)

    # 可上班的人
    PersonCount = [4]*14
    # print("PersonCount",PersonCount)

    # 递归计算出所有上班的可能
    DiGuiAlgo(scheduled_list,PersonCount,0)  #参数依次为：0的个数，当前的scheduled_list;每个id可上班的次数
    global MyCount
    print(MyCount)

def DiGuiAlgo(scheduled_list,PersonCount,deep):
    global MyCount
    global AllProbably
    deep = deep + 1
    if deep<22:
        print("deep",deep)
    # 重新开辟一个,才不会影响原来的，用来传递给下一层
    PersonCount0 = []
    PersonCount0 = PersonCount.copy()
    # 再开辟一个影子列表，用来跳出下面的while循环
    PersonCount1 = []
    PersonCount1 = PersonCount.copy()

    scheduled_list0 = []
    scheduled_list0 = scheduled_list.copy()
    
    # 这个循环将把每一个可以用的人再当前空位置上测试一遍，招到合适的就进入下一层
    while sum(PersonCount1) > 0:
        # 统计当前0的个数
        ZerosCount = np.sum(np.where(scheduled_list0,0,1))
        if ZerosCount < 1:
            return
            
        # 拿到PersonCount0中第一个值不为0的下标k
        for i in range(len(PersonCount1)):
            if PersonCount1[i] > 0:
                PersonCount1[i] = 0 #不能直接置为0，因为如果i可以放到上班表里面，还可以继续放i
                break
        
        # 为了区分未排班，将id加1放到排班表里
        if ZerosCount == 1:  # 运行到只剩1个0了
            if MyCheck(scheduled_list0,i):
                scheduled_list0[5,6] = i + 1
                PersonCount0[i] = PersonCount0[i] - 1
                AllProbably.append(scheduled_list0)
                print("---------------------------------------")
                print(scheduled_list0)
                print(PersonCount0)
                print(len(AllProbably))
                MyCount = MyCount + 1
                
        elif ZerosCount > 1:
            if MyCheck(scheduled_list0,i):
                # 定位到当前需要关注的位置，即第a行，第b列
                a = (42 - ZerosCount) // 7
                b = (42 - ZerosCount) % 7
                scheduled_list0[a,b] = i + 1
                PersonCount0[i] = PersonCount0[i]-1
                DiGuiAlgo(scheduled_list0,PersonCount0,deep)


# 检验将id为i+1的人放到scheduled_list表(42 - ZerosCount)位置是否合适
def MyCheck(scheduled_list,i):
    # 统计当前0的个数
    ZerosCount = np.sum(np.where(scheduled_list,0,1))
    # i+1将要放到的位置，即第a行，第b列
    a = (42 - ZerosCount) // 7
    b = (42 - ZerosCount) % 7

    #检验当天这个人是否已有上班
    for k in range(a-1):
        if scheduled_list[k,b] == i+1:#当天这个人已经上班了，就返回False
            return False
    
    #检验这个人前一天是否是航后
    if b >= 1 and (scheduled_list[2,b-1] == i+1 or scheduled_list[3,b-1] == i+1):#当天这个人已经上班了，就返回False
        return False
    
    #检验这个人往前两天是否是夜班
    if b >= 2 and (scheduled_list[4,b-2] == i+1 or scheduled_list[5,b-2] == i+1):#
        return False

    #检验夜班的次数不能大于1
    if np.bincount(scheduled_list[4,:],minlength = i+2)[i+1] + np.bincount(scheduled_list[5,:],minlength = i+2)[i+1] > 0:#第五行、第6行的个数之和不能大于1
        return False

    return True







# 主函数
if __name__=="__main__":
    ScheduledAlgo()